"""
使用线程相关的各种类。
date: 2019-4-22
"""
import threading as thread


class DemoThread:
    """ 最基本的线程案例让两个函数同时执行，但线程并不能确保这两个方法的执行顺序。注意输出结果a和b的打印可能是交替着打印。"""
    def __init__(self):
        t1 = thread.Thread(target=self.a)
        t2 = thread.Thread(target=self.b)
        t1.start()
        t2.start()

    def a(self):
        for _ in range(100):
            print('{: <20d}'.format(_))

    def b(self):
        for _ in range(100):
            print('{: >20d}'.format(_))


class DemoLock:
    """ 通过线程Lock来对执行的顺序进行控制。当a方法执行完之后，b才能执行。"""
    def __init__(self):
        t1 = thread.Thread(target=self.a)
        t2 = thread.Thread(target=self.b)
        self.lock = thread.Lock()
        t1.start()
        t2.start()

    def a(self):
        self.lock.acquire()             # 可以使用with self.lock:来取代当前行和第四行。
        for _ in range(100):
            print('{: <20d}'.format(_))
        self.lock.release()             # 第四行。

    def b(self):
        self.lock.acquire()
        for _ in range(100):
            print('{: >20d}'.format(_))
        self.lock.release()


class DemoCondition:
    """ 条件控制需要在锁中使用，相比Lock，Condition多了wait和notify、notifyAll方法来实现不同线程之间的控制。"""
    def __init__(self):
        t1 = thread.Thread(target=self.a)
        t2 = thread.Thread(target=self.b)
        self.condition = thread.Condition()
        t1.start()
        t2.start()

    def a(self):
        with self.condition:                    # 条件控制本身就是线程锁，使用锁后再进行wait和notify的控制。
            for _ in range(100):
                print('{: <20d}'.format(_))
                if _ == 50:
                    self.condition.notify()     # 执行到50唤醒其他被wait阻塞的方法。
                    self.condition.wait()       # 然后自己进入阻塞。

    def b(self):
        with self.condition:                    # 只有被notify唤醒才能执行。
            for _ in range(100):
                print('{: >20d}'.format(_))
            self.condition.notify()             # 唤醒a方法50后的计算。


class DemoEvent:
    """ 通过Event来对a和b的执行进行控制，set方法用来唤醒wait的等待。"""
    def __init__(self):
        t1 = thread.Thread(target=self.a)
        t2 = thread.Thread(target=self.b)
        self.event = thread.Event()
        t1.start()
        t2.start()

    def a(self):
        for _ in range(100):
            print('{: <20d}'.format(_))
        self.event.set()                    # 唤醒wait。

    def b(self):
        self.event.wait()                   # 如果执行到了wait会一直等待下去，直到set方法来唤醒wait。
        for _ in range(100):
            print('{: >20d}'.format(_))

            
DemoCondition()